The Almighty 3 Point Shot

code
sports
analysis
Author

Gop Arop

Published

May 9, 2024

A look into three-pointers in the NBA.

Abstract

The prominence of the three-point shot in the NBA is currently a hot topic in the sports world. When the three-point shot was first introduced in the 1979-80 NBA season, the shot was looked at, for quite a while, as a novelty shot. Coaches, players, and executives did not strategize their teams and/or game plans around the three-point shot at all. In fact, many discouraged players from shooting them at all. So what has changed? How much of a impact has the three-point shot had on the scoring the NBA today? Digging deeper into that question, I found that the percentage of shots taken and made from three point land has increase gradually over the course of the last 24 seasons. Notably, I found a significant jump in average three-point attempts by the top 20 scorers in the NBA from the 2015 season to the 2016 season (3.370 - 5.125).

Introduction

The Data

In the making of this project, I extracted data from 3 main sources. 2 of the most influential packages I worked with were BasketballAnalyzeR and HoopR. Both these packages come from GitHub.com. The other source of data I used was BasketballReference.com, the data I used was obtained via webscraping.

Sample Oberservations

Observations for top 6 scorers in the NBA for the 2022-23 season. I used this data set to construct a visualization of the average number of three pointer attempted by the top 20 NBA players over the last 24 seasons.

PLAYER_ID RANK PLAYER TEAM_ID TEAM GP MIN FGM FGA FG_PCT FG3M FG3A FG3_PCT FTM FTA FT_PCT OREB DREB REB AST STL BLK TOV PTS EFF Season
1629029 1 Luka Doncic 1610612742 DAL 70 37.5 11.5 23.6 0.487 4.1 10.6 0.382 6.8 8.7 0.786 0.8 8.4 9.2 9.8 1.4 0.5 4 33.9 36.9 2023-24
203507 2 Giannis Antetokounmpo 1610612749 MIL 73 35.2 11.5 18.8 0.611 0.5 1.7 0.274 7 10.7 0.657 2.7 8.8 11.5 6.5 1.2 1.1 3.4 30.4 36.4 2023-24
1628983 3 Shai Gilgeous-Alexander 1610612760 OKC 75 34 10.6 19.8 0.535 1.3 3.6 0.353 7.6 8.7 0.874 0.9 4.7 5.5 6.2 2 0.9 2.2 30.1 32.2 2023-24
1628973 4 Jalen Brunson 1610612752 NYK 77 35.4 10.3 21.4 0.479 2.7 6.8 0.401 5.5 6.5 0.847 0.6 3.1 3.6 6.7 0.9 0.2 2.4 28.7 25.6 2023-24
201142 5 Kevin Durant 1610612756 PHX 75 37.2 10 19.1 0.523 2.2 5.4 0.413 4.8 5.6 0.856 0.5 6.1 6.6 5 0.9 1.2 3.3 27.1 27.7 2023-24
1626164 6 Devin Booker 1610612756 PHX 68 36 9.4 19.2 0.492 2.2 6.1 0.364 6 6.7 0.886 0.8 3.7 4.5 6.9 0.9 0.4 2.6 27.1 26.7 2023-24

Variables of Interest

These variables were the only ones used I used throughout my project.

Variables
PLAYER_NAME
EVENT_TYPE
PLAYER_ID
SHOT_TYPE
PTS
EFF
FG3M
FG3A
FG3_PCT
Season

Visualization

seasons_choice <- paste0(substr(seq(2023, 1999), 1, 4), "-", substr(seq(2024, 2000), 3, 4)) |> as.factor()

`2000's` <- paste0(substr(seq(2008, 1999), 1, 4), "-", substr(seq(2009, 2000), 3, 4))
`2010's` <- paste0(substr(seq(2018, 2009), 1, 4), "-", substr(seq(2019, 2010), 3, 4))

season_alt <- paste0(seq(2000,2024)) |>
  as.factor()
top_scorers_df <- tibble(Player = character(),
                            PTS = numeric(),
                            Season = character(),
                            stringsAsFactors = FALSE)

for (season in seasons_choice) {
  players <- nba_leagueleaders(season = season, 
                                stat_category = "PTS", 
                                per_mode = "PerGame")
  
  players <- players[["LeagueLeaders"]] |>
    mutate(PTS = as.numeric(PTS))
  
  players <- players |>
    arrange(desc(PTS)) |>
    slice(1:30)
  
  top_scorers_df <- rbind(top_scorers_df, 
                         transform(players, Season = season))
}
top_scorers_df <- top_scorers_df |>
    mutate(`Season` = as.factor(`Season`),
           `FG3A` = as.numeric(`FG3A`))
top_scorers_plot <- top_scorers_df |>
  mutate(DECADE = case_when(Season %in% `2000's` ~ "2000s",
                            Season %in% `2010's` ~ "2010s",
                            .default = "Early 2020s")) |>
  group_by(Season, DECADE) |>
  summarise(`Average 3 Point Attempt Per Game` = mean(`FG3A`)) |>
  bind_cols(season_alt) |>
  rename(`Season Alt` = `...4`) |>
  rename(Year = `Season Alt`) |>
  mutate(`Average 3 Point Attempt Per Game` = round(`Average 3 Point Attempt Per Game`, 3))
`summarise()` has grouped output by 'Season'. You can override using the
`.groups` argument.
New names:
timeplot <- ggplot(data = top_scorers_plot, aes(x = `Year`, y = `Average 3 Point Attempt Per Game`, group = DECADE, color = DECADE, label = `Year`)) + 
  geom_point() + 
  geom_line() + 
  facet_grid(~DECADE, scales = "free_x") + 
  theme_bw() +
  theme(legend.position = "bottom",legend.title = element_blank(), legend.background = element_rect(fill = "white", color = "black"), axis.text.x = element_blank(), axis.ticks.x = element_blank()) + labs(x = "Season") +scale_color_viridis_d()

ggplotly(timeplot, tooltip = c("label", "y"))

In this visualization, the data was tidyed for the top 30 scorers per game for the last 24 NBA seasons. The graph visualizes the average three pointers attempted per game from those 30 players and plots the points over the course of 24 seasons. The interactivity of the plot allows the user to hover over the points and see what year and the data point represents.

From this plot, I found that the greatest jump over the last 24 seasons, in attempted three pointers per game occurred two years in a row (2015-2016 & 2016-2017). This most likely had to do with Steph Curry’s run of championships and success heaving up a high volume of three-pointers. Although the average attempts are at a record high, this current season actually produced the lowest average, for the top 30 scorers, in the last 6 years. It will be interesting to see if this decrease in three-pointers attempted becomes a trend for years to come.

Conclusion

In the future, I would like to be able to develop predictive models and run statistical tests to come up with more conclusive results.